import { ipcMain, ipcRenderer } from "electron";
import E from "@/utils/events_bus/events.js";

class Events {
  constructor() {}
  /**
   *
   * @param {String} params.channel 通信的频道
   * @param {any} params.data 发送的数据
   * @param {String | Array | Null} params.name 需要给哪个窗口发送消息，不传则给所有窗口发送消息
   */
  static send(params) {
    let { channel, data, name } = {
      channel: "",
      data: null,
      name: null,
      ...params,
    };
    if (!channel) {
      throw new Error("channel is required!"); // 如果没有指定事件名称，则抛出错误
    }
    if (process.type !== "renderer") {
      throw new Error("send() can only be used in renderer process!");
    }
    ipcRenderer.send("event_bus", {
      channel,
      data,
      name,
    }); // 调用 ipcRenderer 的 send 方法发送事件
  }
  static on(channel, callback) {
    // 监听事件
    if (process.type !== "renderer") {
      throw new Error("on() can only be used in renderer process!");
    }
    let CHANNEL = channel.toUpperCase(); // 将事件名称转换为大写;
    ipcRenderer.on(CHANNEL, (e, param) => {
      // 调用 ipcRenderer 的 on 方法监听事件
      callback(param); // 执行回调函数
    });
  }
  static send_reply(channel, data) {
    return new Promise((resolve) => {
      ipcRenderer.send(channel, data);
      ipcRenderer.once(`${channel}-reply`, (_, result) => resolve(result));
    });
  }

  static init(win_dict) {
    ipcMain.on("event_bus", (e, param) => {
      // 调用 ipcMain 的 on 方法监听事件
      if (!process.type === "browser") {
        throw new Error("init() can only be used in the main process!");
      }
      const CHANNEL = param.channel.toUpperCase(); // 将事件名称转换为大写;
      const sender = e.sender; // 获取事件的发送者
      if (param.name) {
        // 如果指定的窗口不存在，则直接返回
        if (!win_dict[param.name]) {
          return;
        }
        // 如果指定的窗口是当前窗口，则直接返回
        if (win_dict[param.name].webContents === sender) {
          return;
        }
        win_dict[param.name].webContents.send(CHANNEL, param.data);
      } else {
        for (let key in win_dict) {
          // 遍历 win_dict 对象的所有属性
          if (
            win_dict[key].webContents !== sender &&
            !win_dict[key].isDestroyed()
          ) {
            win_dict[key].webContents.send(CHANNEL, param.data); // 调用 webContents 的 send 方法发送事件
          }
        }
      }
    });
    for (const [event, handler] of Object.entries(E)) {
      ipcMain.on(event, async (e, data) => {
        const result = await handler(e, data);
        e.reply(`${event}-reply`, result);
      });
    }
  }
}

Events.IPC = {
  Main: ipcMain,
  Renderer: ipcRenderer,
};

export { Events };
